import 'dart:convert';

import 'package:dio/dio.dart';
import 'package:flutter_shop/helpers/LoggerFormat.dart';
import 'package:flutter_shop/helpers/utils.dart';
import 'package:logger/logger.dart';

class HttpBaseResult<D> {
  String code;
  String message;
  D data;
}

typedef Future<HttpBaseResult<T>> HandlerSuccessFunc<T>();
typedef Future<HttpBaseResult<T>> HandlerFailFunc<T>();
const String baseUrl = "https://wxmini.baixingliangfan.cn/baixing/";

class HttpProxy<D> {
  static final String host = baseUrl;
  static String token;
  String _method;
  String _path;
  final Dio _dio = Dio();
  Map<String, Object> _headers = {};
  Map<String, Object> _urlArgs = {};
  Map<String, Object> _bodyArgs = {};
  HandlerSuccessFunc<D> successFunc;
  HandlerFailFunc<D> failFunc;

  HttpProxy.get(this._path, this._urlArgs) : assert(_path != null) {
    this._method = "GET";
  }

  HttpProxy.post(this._path, this._urlArgs, this._bodyArgs)
      : assert(_path != null) {
    this._method = "POST";
  }

  Future<HttpBaseResult<D>> send<D>() async {
    if (!this._path.startsWith(RegExp(r"http[s]?"))) {
      this._path = HttpProxy.host + this._path;
    }
    return await this._send();
  }

  Future<HttpBaseResult> _send() async {
    this._setHeaders();
    if (this._method == 'POST') {
      return await this._sendPost();
    } else if (this._method == 'GET') {
      return await this._sendGet();
    } else {
      throw new ArgumentError('invalid http method');
    }
  }

  Future<HttpBaseResult> _sendPost() async {
    String data = JsonEncoder().convert(this._bodyArgs);
    logger.debug("send requset post ${this._path} $data");
    Response response = await this
        ._dio
        .post(this._path, data: data, queryParameters: this._bodyArgs);
    return this._handleRes(response);
  }

  Future<HttpBaseResult> _sendGet() async {
    try {
      Response response =
          await this._dio.get(this._path, queryParameters: this._urlArgs);
      return this._handleRes(response);
    } catch (e) {
      print(e);
      throw "http 请求失败";
    }
  }

  HttpBaseResult _handleRes(Response response) {
    var _rawResult = response.data;
    var result;
    int httpStatusCode = response.statusCode;
    String msg = response.statusMessage;
    if (_rawResult != null) {
      if (_rawResult.runtimeType == String) {
        result = jsonDecode(_rawResult);
        result["data"] = Utils.camelize(result["data"]);
      }
    }
    if (httpStatusCode != 200) {
      this._handleCommonError(msg);
      return null;
    } else {
      var res = HttpBaseResult();
      res.code = result["code"];
      res.message = result["message"];
      res.data = result["data"];
      return res;
    }
  }

  void _handleCommonError(String msg) {
    // NOTE: 暂时不处理服务器
    print(msg);
  }

  void _setHeaders() {
    this._headers['Content_type'] = "application/json";
    this._headers["authorization"] = HttpProxy.token ?? "";
  }
}
